import { useRef, useCallback } from 'react'

interface CacheEntry<T> {
  data: T
  timestamp: number
  promise?: Promise<T>
}

interface UseApiCacheOptions {
  ttl?: number // 缓存时间（毫秒），默认5分钟
  maxSize?: number // 最大缓存条目数，默认100
}

export function useApiCache<T = any>(options: UseApiCacheOptions = {}) {
  const { ttl = 5 * 60 * 1000, maxSize = 100 } = options
  const cacheRef = useRef<Map<string, CacheEntry<T>>>(new Map())
  const debounceTimersRef = useRef<Map<string, NodeJS.Timeout>>(new Map())

  // 清理过期缓存
  const cleanExpiredCache = useCallback(() => {
    const now = Date.now()
    const cache = cacheRef.current
    
    // 使用 Array.from 来避免迭代器问题
    Array.from(cache.entries()).forEach(([key, entry]) => {
      if (now - entry.timestamp > ttl) {
        cache.delete(key)
      }
    })
  }, [ttl])

  // 限制缓存大小
  const limitCacheSize = useCallback(() => {
    const cache = cacheRef.current
    if (cache.size > maxSize) {
      const entries = Array.from(cache.entries())
      entries.sort((a, b) => a[1].timestamp - b[1].timestamp)
      
      // 删除最旧的条目
      const toDelete = entries.slice(0, cache.size - maxSize)
      toDelete.forEach(([key]) => cache.delete(key))
    }
  }, [maxSize])

  // 获取缓存数据
  const getCached = useCallback((key: string): T | null => {
    cleanExpiredCache()
    
    const entry = cacheRef.current.get(key)
    if (entry && Date.now() - entry.timestamp <= ttl) {
      return entry.data
    }
    
    if (entry) {
      cacheRef.current.delete(key)
    }
    
    return null
  }, [ttl, cleanExpiredCache])

  // 设置缓存数据
  const setCached = useCallback((key: string, data: T): void => {
    cleanExpiredCache()
    limitCacheSize()
    
    cacheRef.current.set(key, {
      data,
      timestamp: Date.now()
    })
  }, [cleanExpiredCache, limitCacheSize])

  // 带缓存的API请求
  const fetchWithCache = useCallback(async (
    key: string,
    fetchFn: () => Promise<T>,
    useCache: boolean = true
  ): Promise<T> => {
    // 如果使用缓存，先检查缓存
    if (useCache) {
      const cached = getCached(key)
      if (cached !== null) {
        return cached
      }
    }

    // 检查是否已有相同的请求在进行中
    const entry = cacheRef.current.get(key)
    if (entry?.promise) {
      return entry.promise
    }

    // 创建新的请求
    const promise = fetchFn().then(data => {
      if (useCache) {
        setCached(key, data)
      }
      return data
    }).catch(error => {
      // 请求失败时清理promise引用
      const entry = cacheRef.current.get(key)
      if (entry) {
        delete entry.promise
      }
      throw error
    })

    // 缓存promise引用
    if (useCache) {
      const entry = cacheRef.current.get(key) || { data: null as T, timestamp: 0 }
      entry.promise = promise
      cacheRef.current.set(key, entry)
    }

    return promise
  }, [getCached, setCached])

  // 防抖请求
  const debouncedFetch = useCallback((
    key: string,
    fetchFn: () => Promise<T>,
    delay: number = 300
  ): Promise<T> => {
    return new Promise((resolve, reject) => {
      // 清除之前的定时器
      const existingTimer = debounceTimersRef.current.get(key)
      if (existingTimer) {
        clearTimeout(existingTimer)
      }

      // 设置新的定时器
      const timer = setTimeout(async () => {
        try {
          const result = await fetchWithCache(key, fetchFn)
          resolve(result)
        } catch (error) {
          reject(error)
        } finally {
          debounceTimersRef.current.delete(key)
        }
      }, delay)

      debounceTimersRef.current.set(key, timer)
    })
  }, [fetchWithCache])

  // 清除缓存
  const clearCache = useCallback((key?: string): void => {
    if (key) {
      cacheRef.current.delete(key)
      debounceTimersRef.current.delete(key)
    } else {
      cacheRef.current.clear()
      debounceTimersRef.current.clear()
    }
  }, [])

  // 预加载数据
  const preload = useCallback(async (
    key: string,
    fetchFn: () => Promise<T>
  ): Promise<void> => {
    try {
      await fetchWithCache(key, fetchFn)
    } catch (error) {
      console.warn('Preload failed:', error)
    }
  }, [fetchWithCache])

  return {
    getCached,
    setCached,
    fetchWithCache,
    debouncedFetch,
    clearCache,
    preload
  }
}
